package com.apobates.forum.thrones.controller;

import com.apobates.forum.core.ImageIOMeta;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.proxy.BoardReplica;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.core.service.BoardGroupService;
import com.apobates.forum.core.service.BoardService;
import com.apobates.forum.core.service.TopicService;
import com.apobates.forum.thrones.exception.ResourceNotFoundException;
import com.apobates.forum.thrones.spa.DocumentPage;
import com.apobates.forum.thrones.spa.EntryItem;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 帮助中心控制器 内置的help文件夹; 栏目,子栏目,文章
 *
 * @author xiaofanku
 * @since 20200616
 */
@Controller
@RequestMapping(value = "/article")
public class SectionArticleController {
    @Autowired
    private BoardGroupService boardGroupService;
    @Autowired
    private BoardService boardService;
    @Autowired
    private TopicService topicService;
    @Autowired
    private ImageIOMeta imageIOMeta;
    
    //各个模板都起作用的(栏目/子栏目)
    @GetMapping(path = "/{section}/{term}/{id}.xhtml")
    public String getArticle(
            @PathVariable("section") String sectionDirectoryName,
            @PathVariable("term") String termDirectoryName,
            @PathVariable("id") long articleId,
            HttpServletRequest request,
            Model model) {
        BoardReplica term = boardService.getTermRelateSection(termDirectoryName).orElseThrow(()->new ResourceNotFoundException("子栏目不存在或暂时无法访问"));
        TopicReplica article = topicService.getTermArticleContent(articleId, imageIOMeta).orElseThrow(()->new ResourceNotFoundException("文章不存在或暂时无法访问"));
        DocumentPage dp = DocumentPage.buildViewPage(article, term);
        model.addAttribute("page", dp);
        model.addAttribute("section", new EntryItem(term.getVolumes().getTitle(), String.format("/article/home?m=%s", term.getVolumes().getDirectoryNames())));
        return "default/" + sectionDirectoryName + "/" + termDirectoryName + "/view";
    }
    
    //单个内容页(只用到了栏目的模板)
    @GetMapping(path = "/page")
    public String pageView(
            @RequestParam("bd") String termDirectoryName, //?
            @RequestParam(value = "id", required = false, defaultValue = "0") long articleId,
            HttpServletRequest request,
            Model model) {
        BoardReplica term = boardService.getTermRelateSection(termDirectoryName).orElseThrow(()->new ResourceNotFoundException("子栏目不存在或暂时无法访问"));
        Optional<TopicReplica> articleReplica = (articleId > 0)?topicService.getTermArticleContent(articleId, imageIOMeta):topicService.getFirstArticleForTerm(term.getId(), imageIOMeta); //子栏目的第一篇文章
        TopicReplica article = articleReplica.orElseThrow(()->new ResourceNotFoundException("文章内容不存在或暂时无法访问"));
        DocumentPage dp = DocumentPage.buildViewPage(article, term);
        model.addAttribute("page", dp);
        model.addAttribute("section", new EntryItem(term.getVolumes().getTitle(), String.format("/article/home?m=%s", term.getVolumes().getDirectoryNames())));
        return "default/" + term.getVolumes().getDirectoryNames() + "/view";
    }
    
    //modelName的开始页
    @GetMapping(path = "/home")
    public String homeView(
            @RequestParam("m") String sectionDirectoryName, //?
            HttpServletRequest request,
            Model model) {
        BoardGroup sectionObj = boardGroupService.getOriginByDirectoryNames(sectionDirectoryName).orElseThrow(()->new ResourceNotFoundException("目标对象不存在"));
        List<Board> terms = boardService.getAllTermByOriginId(sectionObj.getId());
        //
        model.addAttribute("page", DocumentPage.buildHomePage(sectionObj, terms));
        return "default/" + sectionDirectoryName + "/index";
    }
    
    //右侧的导航{版块名:xxx, 话题:[{},{}]}
    @GetMapping(path = "/menu", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getPageMenu(
            @RequestParam("bd") String termDirectoryName, //?
            @RequestParam("id") long articleId,
            HttpServletRequest request,
            Model model) {
        Optional<Board> term = boardService.getTermByDirectoryNames(termDirectoryName);
        if (!term.isPresent()) {
            return "{}";
        }
        Board termObj = term.get();
        EntryItem key = new EntryItem(termObj.getTitle(), String.format("/article/page?bd=%s", termDirectoryName));
        //
        Comparator<EntryItem> byTimestamp = Comparator.comparing(EntryItem::getLink);
        Supplier<TreeSet<EntryItem>> supplier = () -> new TreeSet<>(byTimestamp);
        Set<EntryItem> entries = topicService.getAllByBoard(termObj.getId(), ForumEntityStatusEnum.ACTIVE)
                .map(t -> new EntryItem(t.getTitle(), String.format("/article/page?bd=%s&id=%d", termDirectoryName, t.getId())))
                .collect(Collectors.toCollection(supplier));
        //
        Type setType = new TypeToken<TreeSet<EntryItem>>() {}.getType();
        Gson gson = new GsonBuilder().disableHtmlEscaping().create(); //Unicode转义字符(= / \u003d)
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("parent", gson.toJson(key));
        jsonObject.add("menu", gson.toJsonTree(entries, setType));
        return jsonObject.toString();
    }
    
    //指定文章的上一条|下一条
    @GetMapping(path = "/navigate", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<String, EntryItem> getPageNavigator(
            @RequestParam("bd") final String termDirectoryName, //?
            @RequestParam("id") long articleId,
            HttpServletRequest request,
            Model model) {
        Optional<Board> term = boardService.getTermByDirectoryNames(termDirectoryName);
        if (!term.isPresent()) {
            return Collections.emptyMap();
        }
        Map<String, Topic> data = topicService.getPrevNextTermArticle(term.get().getId(), articleId);
        Function<Entry<String,Topic>, String> keyMapper = entry->entry.getKey().toLowerCase();
        Function<Entry<String,Topic>, EntryItem> valueMapper = entry->new EntryItem(entry.getValue().getTitle(), String.format("/article/page?bd=%s&id=%d", termDirectoryName, entry.getValue().getId()));
        return data.entrySet().stream().collect(Collectors.toMap(keyMapper,valueMapper));
    }
}